﻿/*
 *  ChgDoc CMS - GNU General Public License, version 3 (GPL-3.0)
 *  Copyright (C)  2012. Ian Quigley
 *  
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Script.Services;
using ChgDoc.Entity;
using ChgDoc.Render;
using SqliteORM;

namespace ChgDoc.Service
{
    /// <summary>
    /// Summary description for Article
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [ScriptService]
    public class Article : System.Web.Services.WebService
    {
        [WebMethod( EnableSession = true )]
        [ScriptMethod( ResponseFormat = ResponseFormat.Json )]
        public Result SetBody( long articleId, string body )
        {
            if (!Visitor.HasPermission( "Admin" ))
                return new ResultFail( "You need Admin permission" );

            var article = ChgDoc.Entity.Article.Read( articleId );
            if (article == null)
                return new ResultFail( "Could not find ArticleId: " + articleId );

            article.Body = HttpUtility.UrlDecode( body );
            article.Save();

            Config.ClearCaches();

            return new ResultOk();
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod( ResponseFormat = ResponseFormat.Json )]
        public Result Locations(long articleId)
        {
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            return new ResultListKVP<long>( from loc in article.Locations() select new KeyValuePair<long, string>( loc.Id, loc.Name ) );
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod( ResponseFormat = ResponseFormat.Json )]
        public Result AddLocation( long articleId, long locationId )
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");

            var article = ChgDoc.Entity.Article.Read( articleId );
            if (article == null)
                return new ResultFail( "Could not find ArticleId: " + articleId );
            
            article.AddLocation( locationId );
            return new ResultOk();
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result DeleteLocation(long articleId, long locationId)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");
            
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            article.DeleteLocation(locationId);
            return new ResultOk();
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result SortLocationOrder(long locationId, int[] articles)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");

            int sortIndex = 1;            
            using (var adapter = TableAdapter<ArticleLocation>.Open())
            {
                adapter.Delete( Where.Equal( "LocationId", locationId ) );
                foreach (int articleId in articles)
                    adapter.CreateUpdate( new ArticleLocation() { LocationId = locationId, ArticleId = articleId, SortOrder = sortIndex++ } );
            }

            return new ResultOk();
        }
		
		[WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result SortTagOrder(long tagId, int[] articles)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");

            int sortIndex = 1;            
            using (var adapter = TableAdapter<ArticleTag>.Open())
            {
                adapter.Delete( Where.Equal( "TagId", tagId ) );
                foreach (int articleId in articles)
                    adapter.CreateUpdate( new ArticleTag() { TagId = tagId, ArticleId = articleId, SortOrder = sortIndex++ } );
            }

            return new ResultOk();
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result Tags(long articleId)
        {
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            return new ResultListKVP<long>( from loc in article.Tags() select new KeyValuePair<long, string>( loc.Id, loc.Name ) );
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result AddTag(long articleId, long tagId)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");

            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            article.AddTag(tagId);
            return new ResultOk();
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result DeleteTag(long articleId, long tagId)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");
            
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            article.DeleteTag(tagId);
            return new ResultOk();
        }


        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result Urls(long articleId)
        {
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            return new ResultListKVP<long>( from loc in article.Urls() select new KeyValuePair<long, string>( loc.Id, loc.Url ) );
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result AddUrl(long articleId, long templateId, string url)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");
            
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            if (string.IsNullOrWhiteSpace(url))
                return new ResultFail("URL should not be empty");

            PageResponse test = PageResponse.Read(url);
            if (test != null)
                return new ResultFail(url + " already exists");

            if (!PageResponse.IsValidUrl(url))
                return new ResultFail(url + " contains invalid characters");

            PageResponse resp = new PageResponse();
            resp.Url = url;
            resp.Render = PageRender.TemplateData;
            TemplateDataRenderParameters param = new TemplateDataRenderParameters();
            param.Id = articleId.ToString();
            param.Table = "Article";
            param.TemplateId = templateId;
            resp.RenderOptions = param.Serialize();
            resp.Save();

            article.AddPageResponse(resp.Id);
            return new ResultOk();
        }

        [WebMethod(EnableSession=true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result DeleteUrl(long articleId, long urlId)
        {
            if (!Visitor.HasPermission("Admin"))
                return new ResultFail("You need Admin permission");
            
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            article.DeletePageResponse(urlId);
            return new ResultOk();
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result Attributes(long articleId)
        {
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            return new ResultListKVP<string>(from attr in article.Attributes() select new KeyValuePair<string, string>(attr.Code, attr.Value));
        }

        [WebMethod(EnableSession = true)]
        [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
        public Result EditAttribute(long articleId, string code, string value)
        {
            var article = ChgDoc.Entity.Article.Read(articleId);
            if (article == null)
                return new ResultFail("Could not find ArticleId: " + articleId);

            value = HttpUtility.UrlDecode( value );

            if (string.Equals(code, "new/value", StringComparison.OrdinalIgnoreCase) && value.IndexOf("/") != -1)
            {
                code = value.Substring(0, value.IndexOf("/"));
                value = value.Substring(value.IndexOf("/") + 1);
            }
            article.Attribute(code, value);

            Config.ClearCaches();

            return new ResultOk();
        }

        [WebMethod( EnableSession = true )]
        [ScriptMethod( ResponseFormat = ResponseFormat.Json )]
        public Result DeleteAttribute( long articleId, string code )
        {
            EntityAttribute.Delete( EntityType.Article, code );
            return new ResultOk();
        }
       
        
    }
}
